package com.xyy.saas.payment.service.job.impl;

import com.alibaba.fastjson.JSON;
import com.xyy.saas.payment.adapter.channel.fm.config.BankConfigManager;
import com.xyy.saas.payment.common.constants.ApolloConstants;
import com.xyy.saas.payment.constants.Constants;
import com.xyy.saas.payment.dao.mapper.RefundOrderMapper;
import com.xyy.saas.payment.dao.mapper.WithdrawOrderMapper;
import com.xyy.saas.payment.dao.model.*;
import com.xyy.saas.payment.enums.TradeTypeEnum;
import com.xyy.saas.payment.exception.PaymentException;
import com.xyy.saas.payment.manage.cores.bo.SyncFMPayReportConfigBO;
import com.xyy.saas.payment.pojo.bo.FuminRecordBo;
import com.xyy.saas.payment.pojo.bo.QueryFuminRecordBo;
import com.xyy.saas.payment.pojo.vo.QueryFuminRecordVo;
import com.xyy.saas.payment.service.PayReportService;
import com.xyy.saas.payment.service.SeparateOrderService;
import com.xyy.saas.payment.service.UserInfoService;
import com.xyy.saas.payment.service.job.SyncFuminDataService;
import com.xyy.saas.payment.service.report.QueryFuminService;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.DateUtil;
import com.xyy.saas.payment.util.JSONUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.DependsOn;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import util.AESUtil;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@DependsOn({"apolloUtil"})
@Service
public class SyncFuminDataServiceImpl implements SyncFuminDataService {
    private static final Logger LOGGER = LoggerFactory.getLogger(SyncFuminDataServiceImpl.class);

    @Resource
    private SeparateOrderService separateOrderService;
    @Resource
    private PayReportService payReportService;
    @Resource
    private WithdrawOrderMapper withdrawOrderMapper;
    @Resource
    private RefundOrderMapper refundOrderMapper;
    @Resource
    private QueryFuminService queryFuminService;
    @Resource
    private ChannelSftpService channelSftpService;
    @Resource
    private ChannelSftpService2 channelSftpService2;
    @Resource
    private BankConfigManager bankConfigManager;
    @Resource
    private UserInfoService userInfoService;

    SimpleDateFormat otherReportFormatter = new SimpleDateFormat("yyyy-MM-dd");
    SimpleDateFormat payReportFormatter = new SimpleDateFormat("yyyyMMdd");

    @Override
    public void synchronizeLastDayFuminData() {
        bankConfigManager.getFuminAccountConfig().forEach(item -> {
            String lastDay = DateUtil.getYestoday3();
            LOGGER.info("SyncFuminDataServiceImpl#synchronizeLastDayFuminData queryFuminRecords begin SyncFMPayReportConfigBO:{}, lastDay:{}", JSONUtils.toJSON(item), lastDay);
            synchronizeFuminDataByDay(lastDay, lastDay, item);
            LOGGER.info("SyncFuminDataServiceImpl#synchronizeLastDayFuminData queryFuminRecords end SyncFMPayReportConfigBO:{} , lastDay:{}", JSONUtils.toJSON(item), lastDay);
        });
    }

    @Override
    public void synchronizeFuminDataByDay(String startDay, String endDay, SyncFMPayReportConfigBO config) {
        LOGGER.info("ChannelServiceImpl#synchronizeFuminData queryFuminRecords begin SyncFMPayReportConfigBO:{}", JSONUtils.toJSON(config));
        boolean hasNext;
        int pageNo = 0;

        do{
            pageNo++;
            hasNext = queryFuminRecordsByDay(startDay, endDay, config, pageNo);
        }
        while(hasNext);

        LOGGER.info("ChannelServiceImpl#synchronizeFuminData queryFuminRecords finish SyncFMPayReportConfigBO:{}", JSONUtils.toJSON(config));
    }

    public boolean queryFuminRecordsByDay(String startDay, String endDay, SyncFMPayReportConfigBO config, int pageNo) {
        QueryFuminRecordVo queryFuminRecordVo = new QueryFuminRecordVo();
        queryFuminRecordVo.setBeginTime(startDay);
        queryFuminRecordVo.setEndTime(endDay);
        queryFuminRecordVo.setAccountId(config.getAccountId());
        queryFuminRecordVo.setPageNo(pageNo);
        QueryFuminRecordBo fuminRecord;

        try {
            fuminRecord = queryFuminService.queryFuminRecord(queryFuminRecordVo);
        }
        catch(PaymentException e) {
            LOGGER.info("SyncFuminDataServiceImpl#queryFuminRecordsByDay error.", e);
            return false;
        }

        if(fuminRecord.getRecords().size() > 0) {
            for(FuminRecordBo fr : fuminRecord.getRecords()) {
                saveRecordsByFuminRecordBo(fr, config);
            }
        }

        return pageNo < getTotalPage(fuminRecord.getTotalSize());
    }

    @Override
    public void syncPayOrderFromFm() {
        try {
            String date = payReportFormatter.format(DateUtil.getYestoday(DateUtil.getToday()));

            // 药帮忙
            String merchantNoByYBM = bankConfigManager.getFuminBankMch("ec_pop");
            channelSftpService2.download(merchantNoByYBM,merchantNoByYBM + "_" + "01" + "_" + date + ".txt");

            // 荷叶健康
            String merchantNoByHY = bankConfigManager.getFuminBankMch("yikuaiqian_fm");
            channelSftpService2.download(merchantNoByHY, merchantNoByHY + "_" + "01" + "_" + date + ".txt");
        }
        catch(Exception ex) {
            LOGGER.error(ex.getMessage() ,ex);
        }
    }

    @Override
    public void syncOtherOrderFromFm() {
        try {
            String date = otherReportFormatter.format(DateUtil.getYestoday(DateUtil.getToday()));

            // 药帮忙
            String merchantNoByYBM = bankConfigManager.getFuminBankMch("ec_pop");
            channelSftpService.download(merchantNoByYBM, date, merchantNoByYBM + "-" + date + ".txt");

            // 荷叶健康
            String merchantNoByHY = bankConfigManager.getFuminBankMch("yikuaiqian_fm");
            channelSftpService.download(merchantNoByHY, date, merchantNoByHY + "-" + date + ".txt");
        }
        catch(Exception ex) {
            LOGGER.error(ex.getMessage() ,ex);
        }
    }

    private void saveRecordsByFuminRecordBo(FuminRecordBo fuminRecordBo, SyncFMPayReportConfigBO config) {
        PayReport payReport = new PayReport();
//        payReport.setAccountName(fuminRecordBo.getAccountOutName());
        payReport.setAccountType(config.getAccountType());
        payReport.setBusinessType(config.getBusinessType());
        payReport.setPayNo(fuminRecordBo.getFlowNo());
        payReport.setCostType(fuminRecordBo.getDirection().equals("1") ? "IN" : "OUT");
        payReport.setDealTime(DateUtil.sdf1ToDate(fuminRecordBo.getTradeDate()));
        payReport.setAmount(new BigDecimal(fuminRecordBo.getAmount()));
        payReport.setResidual(new BigDecimal(fuminRecordBo.getBalance()));
        payReport.setOppositeAccount(fuminRecordBo.getAccountOut());
        payReport.setOppositeName(fuminRecordBo.getAccountOutName());
        payReport.setAccountIn(fuminRecordBo.getAccountIn());
        payReport.setAccountInName(fuminRecordBo.getAccountInName());

        Arrays.stream(TradeTypeEnum.values()).forEach(item -> {
            if(item.getCode().equals(fuminRecordBo.getTradeType())) {
                payReport.setRemark(item.getDesc());
            }
        });

        String memo = fuminRecordBo.getMemo() == null ? "" : fuminRecordBo.getMemo();
        payReport.setRemark((StringUtils.isBlank(payReport.getRemark()) ? "" : payReport.getRemark()) + "|" + memo);
        SeparateOrder separateOrder = separateOrderService.querySeparateOrderBySeparateNo(payReport.getPayNo());
        if(separateOrder != null) {
            payReport.setBusinessNo(separateOrder.getBusinessOrderNo());
            payReport.setMerchantName(memo);
        }
        payReport.setCreateTime(new Date());
        payReport.setUpdateTime(new Date());
        if("PROCEDURE".equals(config.getAccountType())) {
            // 手续费就从数据库里取一下商家名称
           WithdrawOrder withdrawOrder = withdrawOrderMapper.selectByWithdrawNo(payReport.getPayNo());
           if(withdrawOrder != null) {
               payReport.setMerchantName(withdrawOrder.getBusinessUserName());
           }
        }
        if("REFUND".equals(config.getAccountType())) {
            RefundOrder refundOrder = refundOrderMapper.selectByRefundNo(fuminRecordBo.getFlowNo());
            if(null != refundOrder) {
                payReport.setBusinessNo(refundOrder.getBusinessRefundNo());
                // 查询账号名称
                UserInfo userInfo =  userInfoService.queryUserInfoByAccountId(refundOrder.getUserId());

                if(userInfo != null) {
                    try {
                        String basicInfoJson = AESUtil.decrypt(userInfo.getBasicInfo(), ApolloUtil.getProperty(ApolloConstants.USER_INFO_KEY));
                        payReport.setAccountName((String) JSONUtils.getValueFromJson(basicInfoJson, "name"));
                    }
                    catch(Exception ex) {
                        LOGGER.error(ex.getMessage() ,ex);
                        payReport.setAccountName(config.getDesc());
                    }
                }
                else {
                    payReport.setAccountName(config.getDesc());
                }
            }
        }
        // 退款专用户 -- 关联退款单号
        try {
            payReportService.insert(payReport);
        } catch (DuplicateKeyException e) {
            LOGGER.info("ChannelServiceImpl#saveRecordsByFuminRecordBo records exit record:{}", JSON.toJSONString(payReport));
        }
    }

    private int getTotalPage(int totalSize) {
        if(totalSize % Constants.QUERY_FUMIN_DATA_PAGE_SIZE != 0) {
            return totalSize / Constants.QUERY_FUMIN_DATA_PAGE_SIZE + 1;
        } else {
            return totalSize / Constants.QUERY_FUMIN_DATA_PAGE_SIZE;
        }
    }

}
